#include "unigrama.h"
#include "bigrama.h"
#include "trigrama.h"
estructuraAuxiliar unigrama::estructuraAsociada;

const char* unigrama::RUTA_ARCHIVO_UNIGRAMAS="Unigramas.txt";


unigrama::unigrama()
{

}

unigrama::unigrama(string termino)
{
	//this->tupla=  new string[1];
	this->tupla=&termino;//termino
    this->nTerminos=1;
    unigrama::estructuraAsociada.ngramas=this->nTerminos;

    unigrama::estructuraAsociada.add(representacionComoString());
}

unigrama::~unigrama()
{
    //dtor
}

void unigrama::setearMaximaCantidadEnEstructurasAsociadas(int maxNGramas)
{
	unigrama::estructuraAsociada.nroMaximoDeNGramasPermitidos=maxNGramas;
}

unigrama* unigrama::unigramasDeTupla(Tupla tupla)
{
	unigrama* tmp= new unigrama[tupla.nroDeTerminos];
	for (int i=0;i<tupla.nroDeTerminos;i++)
			{
				tmp[i].tupla[0]=tupla.tuplaDeTerminos[i];
			}
	return tmp;
}

void unigrama::agregarUnigramasDeTupla(Tupla tupla)
{
	for (int i=0;i<tupla.nroDeTerminos;i++)
		{
			//new unigrama(tupla[i]);

		}
}



void unigrama::instertarUnigramasDeTupla(Tupla tupla)
{
	for (int i=0;i<tupla.nroDeTerminos;i++)
			{
				//new unigrama(tupla[i]);
		unigrama::estructuraAsociada.ngramas=1;
		unigrama::estructuraAsociada.add(tupla.tuplaDeTerminos[i]);

			}

}

void unigrama::dumpEstructurasAsociadas()
{
	unigrama::estructuraAsociada.dump();

}

void unigrama::recolectarDatosDeBigramas()
{

	if((bigrama::estructuraAsociada.archivosRestantesAUnificar==0)&&(bigrama::estructuraAsociada.archivosRestantesAUnificar==0))
	{
		bigrama::dumpEstructurasAsociadas();
		// recolectar lod datos desde la estrctura.
	}
	else
		unigrama::recolectarDatosDeBigramasDesdeArchivo();

}

void unigrama::recolectarDatosDeBigramasDesdeArchivo()
{
	Parser par;
		if (!par.cargarArchivo(bigrama::RUTA_ARCHIVO_BIGRAMAS))
		{
			unsigned long int unigramasEnArchivo,distintosConFreq1,distintosConFreq2,distintosConFreq2oMas;
			unigramasEnArchivo=distintosConFreq1=distintosConFreq2=distintosConFreq2oMas=0;
			bool finArch=false;

			string nombreDeArchivoEnUso=unigrama::estructuraAsociada.obtenerSiguienteNombreDeArchivo(unigrama::estructuraAsociada.archivosRestantesAUnificar);
			std::ofstream  fs (nombreDeArchivoEnUso.c_str());
			unigrama::estructuraAsociada.archivosRestantesAUnificar++;



			Tupla bigramaConFreq =par.cargarSiguienteLinea();
			if((bigramaConFreq.nroDeTerminos>0)&&(bigramaConFreq.tuplaDeTerminos[0]!=""))
			{


				while(!par.archivoProcesado())
				{
					Tupla posibleNuevoBigrama;

					while((!(finArch=par.archivoProcesado()))&&(!((posibleNuevoBigrama=par.cargarSiguienteLinea()).compareTo(bigramaConFreq,1))))
					{
						unsigned long int freqBigrama=(unsigned long int) atol(posibleNuevoBigrama.tuplaDeTerminos[2].c_str());

						switch(freqBigrama)
						{
							case 1:
							{
								distintosConFreq1++;
								break;
							}

							case 2:
							{
								distintosConFreq2++;
								break;
							}

							default :
							{
								distintosConFreq2oMas++;
								break;
							}
						}


						//delete posibleNuevoBigrama;

					}

					if(!finArch)
					{
						unsigned long int freqBigrama=(unsigned long int) atol(bigramaConFreq.tuplaDeTerminos[2].c_str());

						switch(freqBigrama)
						{
							case 1:
									{
									distintosConFreq1++;
									break;
									}
							case 2:
									{
									distintosConFreq2++;
									break;
									}
							default:
									{
									distintosConFreq2oMas++;
									break;
									}
						}


						fs << unigrama::construirRepresentacion(bigramaConFreq.tuplaDeTerminos[0],0,distintosConFreq1,distintosConFreq2,distintosConFreq2oMas,0,0) << std::endl;
						unigramasEnArchivo++;
						//delete bigramaConFreq;
						distintosConFreq1=distintosConFreq2=distintosConFreq2oMas=0;
					}

					if(unigramasEnArchivo>=unigrama::estructuraAsociada.nroMaximoDeNGramasPermitidos)
					{
						fs.close();
						//delete fs;


						nombreDeArchivoEnUso=unigrama::estructuraAsociada.obtenerSiguienteNombreDeArchivo(unigrama::estructuraAsociada.archivosRestantesAUnificar);
						std::ofstream fs (nombreDeArchivoEnUso.c_str());
						unigrama::estructuraAsociada.archivosRestantesAUnificar++;
						unigramasEnArchivo=0;
					}

					bigramaConFreq=posibleNuevoBigrama;
				}
				//delete bigramaConFreq;
			}

			par.cerrarArchivo();

			fs.close();
			//delete fs;
			if(unigramasEnArchivo==0)
				{
				remove(nombreDeArchivoEnUso.c_str());
				unigrama::estructuraAsociada.archivosRestantesAUnificar--;
				}
		}

}


std::string unigrama::construirRepresentacion(string termino1,  unsigned long int freq, unsigned long int distintosConFreq1, unsigned long int distintosConFreq2, unsigned long int distintosConFreq2oMas,unsigned long int trigramasDistintosMedio,unsigned long int unigramasDistintosAntes)
{
	const int n=snprintf(NULL,0,"%lu",freq);
	char buf1[n+1];
	snprintf(buf1,n+1,"%lu",freq);

	const int m=snprintf(NULL,0,"%lu",distintosConFreq1);
	char buf2[m+1];
	snprintf(buf2,m+1,"%lu",distintosConFreq1);


	const int o=snprintf(NULL,0,"%lu",distintosConFreq2);
	char buf3[o+1];
	snprintf(buf3,o+1,"%lu",distintosConFreq2);

	const int p=snprintf(NULL,0,"%lu",distintosConFreq2oMas);
	char buf4[p+1];
	snprintf(buf4,p+1,"%lu",distintosConFreq2oMas);

	const int q=snprintf(NULL,0,"%lu",trigramasDistintosMedio);
	char buf5[q+1];
	snprintf(buf5,q+1,"%lu",trigramasDistintosMedio);

	const int r=snprintf(NULL,0,"%lu",unigramasDistintosAntes);
	char buf6[r+1];
	snprintf(buf6,r+1,"%lu",unigramasDistintosAntes);


return termino1+" "+(std::string)buf1+" "+(std::string)buf2+" "+(std::string)buf3+" "+(std::string)buf4+" "+(std::string)buf5+" "+(std::string)buf6;
}

void unigrama::recolectarDatosReordenados()
{
unigrama::recolectarDatosDeBigramasReordenadosDesdeArchivo();
	if(Parser::existeArchivo(bigrama::RUTA_ARCHIVO_BIGRAMAS_REORDENADOS))
		remove(bigrama::RUTA_ARCHIVO_BIGRAMAS_REORDENADOS);

unigrama::recolectarDatosDeTrigramasReordenadosDesdeArchivo();

if(Parser::existeArchivo(trigrama::RUTA_ARCHIVO_TRIGRAMAS_REORDENADOS))
	remove(trigrama::RUTA_ARCHIVO_TRIGRAMAS_REORDENADOS);

}


void unigrama::recolectarDatosDeBigramasReordenadosDesdeArchivo()
{

	Parser par;
			if (!par.cargarArchivo(bigrama::RUTA_ARCHIVO_BIGRAMAS_REORDENADOS))
			{
				unsigned long int unigramasEnArchivo,unigramasDistintosAntes;
				unigramasEnArchivo=unigramasDistintosAntes=0;
				bool finArch=false;
				string nombreDeArchivoEnUso=unigrama::estructuraAsociada.obtenerSiguienteNombreDeArchivo(unigrama::estructuraAsociada.archivosRestantesAUnificar);
				std::ofstream fs (nombreDeArchivoEnUso.c_str());
				unigrama::estructuraAsociada.archivosRestantesAUnificar++;



				Tupla bigramaDistinto =par.cargarSiguienteLinea();
				if((bigramaDistinto.nroDeTerminos>0)&&(bigramaDistinto.tuplaDeTerminos[0]!=""))
				{


					while(!par.archivoProcesado())
					{
						Tupla  posibleNuevoBigrama;

						while((!(finArch=par.archivoProcesado()))&&(!((posibleNuevoBigrama=par.cargarSiguienteLinea()).compareTo(bigramaDistinto,1))))
						{
							unigramasDistintosAntes++;
							//delete posibleNuevoBigrama;

						}

						if(!finArch)
						{
							unigramasDistintosAntes++;


							fs << unigrama::construirRepresentacion(bigramaDistinto.tuplaDeTerminos[0],0,0,0,0,0,unigramasDistintosAntes) << std::endl;
							unigramasEnArchivo++;
							//delete bigramaDistinto;
							unigramasDistintosAntes=0;
						}

						if(unigramasEnArchivo>=unigrama::estructuraAsociada.nroMaximoDeNGramasPermitidos)
						{
							fs.close();
							//delete fs;


							nombreDeArchivoEnUso=unigrama::estructuraAsociada.obtenerSiguienteNombreDeArchivo(unigrama::estructuraAsociada.archivosRestantesAUnificar);
							std::ofstream fs (nombreDeArchivoEnUso.c_str());
							unigrama::estructuraAsociada.archivosRestantesAUnificar++;
							unigramasEnArchivo=0;
						}

						bigramaDistinto=posibleNuevoBigrama;
					}
					//delete bigramaDistinto;
				}

				par.cerrarArchivo();

				fs.close();
				//delete fs;
				if(unigramasEnArchivo==0)
					{
					remove(nombreDeArchivoEnUso.c_str());
					unigrama::estructuraAsociada.archivosRestantesAUnificar--;
					}
			}

}

void unigrama::recolectarDatosDeTrigramasReordenadosDesdeArchivo()
{

	Parser par;
			if (!par.cargarArchivo(trigrama::RUTA_ARCHIVO_TRIGRAMAS_REORDENADOS))
			{
				unsigned long int unigramasEnArchivo,trigramasDistintos;
				unigramasEnArchivo=trigramasDistintos=0;
				bool finArch=false;
				string nombreDeArchivoEnUso=unigrama::estructuraAsociada.obtenerSiguienteNombreDeArchivo(unigrama::estructuraAsociada.archivosRestantesAUnificar);
				std::ofstream fs(nombreDeArchivoEnUso.c_str());
				unigrama::estructuraAsociada.archivosRestantesAUnificar++;



				Tupla trigramaDistinto =par.cargarSiguienteLinea();
				if((trigramaDistinto.nroDeTerminos>0)&&(trigramaDistinto.tuplaDeTerminos[0]!=""))
				{


					while(!par.archivoProcesado())
					{
						Tupla  posibleNuevoTrigrama;

						while((!(finArch=par.archivoProcesado()))&&(!((posibleNuevoTrigrama=par.cargarSiguienteLinea()).compareTo(trigramaDistinto,1))))
						{
							trigramasDistintos++;
							//delete posibleNuevoTrigrama;

						}

						if(!finArch)
						{
							trigramasDistintos++;


							fs << unigrama::construirRepresentacion(trigramaDistinto.tuplaDeTerminos[0],0,0,0,0,trigramasDistintos,0) << std::endl;
							unigramasEnArchivo++;
							//delete trigramaDistinto;
							trigramasDistintos=0;
						}

						if(unigramasEnArchivo>=unigrama::estructuraAsociada.nroMaximoDeNGramasPermitidos)
						{
							fs.close();
							//delete fs;


							nombreDeArchivoEnUso=unigrama::estructuraAsociada.obtenerSiguienteNombreDeArchivo(unigrama::estructuraAsociada.archivosRestantesAUnificar);
							std::ofstream fs(nombreDeArchivoEnUso.c_str());
							unigrama::estructuraAsociada.archivosRestantesAUnificar++;
							unigramasEnArchivo=0;
						}

						trigramaDistinto=posibleNuevoTrigrama;
					}
					//delete trigramaDistinto;
				}

				par.cerrarArchivo();

				fs.close();
				//delete fs;
				if(unigramasEnArchivo==0)
					{
					remove(nombreDeArchivoEnUso.c_str());
					unigrama::estructuraAsociada.archivosRestantesAUnificar--;
					}
			}

}
